package com.jerome.election.server.handler;

import com.jerome.election.enums.ApiUrlEnum;
import com.jerome.election.http.HttpConstant;
import com.jerome.election.http.HttpMessageParser;
import com.jerome.election.http.HttpMethodEnum;
import com.jerome.election.http.HttpStatus;
import com.jerome.election.http.Request;
import com.jerome.election.http.Response;
import com.jerome.election.http.server.HttpHandler;
import com.jerome.election.server.ContextUtil;
import com.jerome.election.server.paxos.PaxosMessage;
import com.jerome.election.sync.CenterServer;
import com.jerome.election.util.JsonUtil;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

/**
 * 成员服务逻辑处理器
 * @author Jerome
 * @date 2023/10/18
 */
public class MemberHandler implements HttpHandler {
    @Override
    public void handle(Socket socket) {
        try {
            // Parse the HTTP request from the input stream of the socket
            Request httpRequest = HttpMessageParser.parse2request(socket.getInputStream());
            HttpMethodEnum methodEnum = HttpMethodEnum.getByCode(httpRequest.getMethod());
            switch (methodEnum) {
                case PAXOS:
                    // 走Paxos 同步逻辑和心跳逻辑
                    // socket长连接
                    // 启动Paxos server端连接
                    new CenterServer(socket, new ServerHandler(), ContextUtil.getConfig().getHeartbeatExpiringTime());
                    break;
                case GET:
                    // 获取提案信息
                    handleGetRequest(httpRequest,socket);
                    break;
                default:
                    throw new Exception("not support http method");
            }
        } catch (Exception e) {
            try {
                // If an exception occurs, build an HTTP response containing the exception information
                error(socket,e);
                // Flush the output stream to ensure the response message is sent
                socket.close();
            }catch (IOException e1){
                e1.printStackTrace();
            }
        }

    }


    @Override
    public void error(Socket serverSocket, Exception e) throws IOException {
        //输出失败
        PrintWriter writer = new PrintWriter(serverSocket.getOutputStream());
        writer.print(HttpMessageParser.buildHttpResponse(HttpMessageParser.buildErrorResponse(e)));
        writer.close();
    }
    /**
     * get 请求
     *
     * @param request
     * @param socket
     * @author Jerome
     * @date 2023/9/12 20:06
     */
    private void handleGetRequest(Request request, Socket socket) throws Exception {
        PrintWriter out = new PrintWriter(socket.getOutputStream());
        Response response = new Response();
        response.setCode(HttpStatus.HTTP_OK);
        response.setStatus(HttpStatus.msg(HttpStatus.HTTP_OK));
        response.setVersion(HttpConstant.HTTP_VERSION);
        if (request.getUri().equals(ApiUrlEnum.LEADER.getCode())){
            PaxosMessage leader = ContextUtil.getProposeAccepter().getLeader();
            response.setMessage(leader==null?"{}": JsonUtil.writeValueAsString(leader));
        }else if (request.getUri().equals(ApiUrlEnum.CLUSTERS.getCode())){
            Map<String, Object> map = new HashMap<>(8);
            map.put("clusters",ContextUtil.getConfig().getServerMap());
            map.put("activeNode",ContextUtil.getNodeMap().keySet());
            map.put("leader",ContextUtil.getProposeAccepter().getLeader());
            response.setMessage(JsonUtil.writeValueAsString(map));
        }else if (request.getUri().equals(ApiUrlEnum.STATE.getCode())){
            response.setMessage(ContextUtil.getProposeAccepter().getStateEnum().getCode());
        }else {
            throw new Exception("uri not support");
        }
        // Build an HTTP response based on the request and result
        String httpRes = HttpMessageParser.buildHttpResponse(response);
        out.print(httpRes);
        out.flush();
        socket.close();
    }
}


